using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class ScreenMsgScript  {
	public const float GRID_HIGH = 1.0f;
	public const float GRID_WIDTH = 1.0f;
	public class ScreenNode
	{
		public Vector3 centre;
		public Rect    rectZone;
		public GameObject sphereObject;
		public GameObject grid;
	}
	
	public void SetScreenVh( GameMsgScript gm, int vertical, int horizontal)
	{
		gameMsg = gm;
		Vertical = vertical;
		Horizontal = horizontal;
	}
	
	public void Init()
	{
		for ( int i = 0 ; i < firelist.Length ; ++i )
		{
			firelist[i] = new List<GameObject>();
		}
	}
	
	public void InitScreen()
	{
		float verticalBegin = ( GRID_HIGH * Vertical *0.5f );
		float horizontalBegin = .0f - ( GRID_WIDTH * Horizontal *0.5f );
		
		screenNodes = new ScreenNode[ Vertical, Horizontal ];
		for ( int i = 0 ; i < Vertical ; ++i )
		{
			for ( int j = 0 ; j < Horizontal ; ++j )
			{
				screenNodes[ i, j] = new ScreenNode();
				screenNodes[ i, j].centre = new Vector3( horizontalBegin + GRID_WIDTH * j + GRID_WIDTH * .5f,
					verticalBegin - GRID_HIGH * i - GRID_HIGH * .5f,
					0 );

 				screenNodes[ i, j].rectZone = new Rect( screenNodes[ i, j].centre.x - GRID_WIDTH * .5f,
					screenNodes[ i, j].centre.y - GRID_HIGH * .5f, GRID_WIDTH, GRID_HIGH );
				int gridIndex = i + j;
				if ( gridIndex >= gameMsg.gridTypeConfig.Length )
				{
					gridIndex %= gameMsg.gridTypeConfig.Length;
				}
				GameMsgScript.GridTypeCinfig curGridType = gameMsg.gridTypeConfig[gridIndex];
				screenNodes[ i, j].grid = GridMeshScript.CreateGrid( screenNodes[ i, j].centre, curGridType.gridMaterial,
					i, j, GRID_HIGH );
				GridScript gs = screenNodes[ i, j].grid.AddComponent<GridScript>();
				gs.InitGrid( curGridType.gridType, curGridType.gridDefaultTex, curGridType.gridFocusTex );
				//Zonelist.Add( screenNodes[ i, j] );
			}
		}
	}
	
	public void CreateSphere( float percent )
	{
		
		System.Random rnd = new System.Random();
		Object sp = Resources.Load( "Prefab/Sphere" ) as Object;
		List<ScreenNode> nodeList = new List<ScreenNode>();
		
		for ( int i = 0 ; i < Vertical ; ++i )
		{
			for ( int j = 0 ; j < Horizontal ; ++j )
			{
				nodeList.Add( screenNodes[i,j]);
			}
		}
		
		curSphereNum = (int)(Vertical * Horizontal * percent);
		if ( curSphereNum%2 != 0  )
		{
			++curSphereNum;
		}
		
		for ( int i = 0 ; i < curSphereNum ; i+=2 )
		{
			int index = rnd.Next( 0 , gameMsg.sphereTypeConfig.Length );
			int listIndex = rnd.Next( 0 , nodeList.Count );
			int flag = 0;
			nodeList.RemoveAll( delegate( ScreenNode curZone )
				{
					if ( flag == listIndex )
					{
						
						curZone.sphereObject = GameObject.Instantiate( sp ) as GameObject;
						SphereScript script = curZone.sphereObject.GetComponent<SphereScript>();
						script.Init();
						script.SetSphereType( gameMsg.sphereTypeConfig[index].sphereType , gameMsg.sphereTypeConfig[index].color );
						curZone.sphereObject.transform.position = curZone.centre;
						script.parent = curZone;
						++flag;
						return true;
					}
					++flag;
					return false;
				}
			);
			listIndex = rnd.Next( 0 , nodeList.Count );
			flag = 0;
			
			nodeList.RemoveAll( delegate( ScreenNode curZone )
				{
					if ( flag == listIndex )
					{
						
						curZone.sphereObject = GameObject.Instantiate( sp ) as GameObject;
						SphereScript script = curZone.sphereObject.GetComponent<SphereScript>();
						script.Init();
						script.SetSphereType( gameMsg.sphereTypeConfig[index].sphereType , gameMsg.sphereTypeConfig[index].color );
						curZone.sphereObject.transform.position = curZone.centre;
						script.parent = curZone;
						++flag;
						return true;
					}
					++flag;
					return false;
				}
			);
		}
	}
	
	public void SetFocus( Ray ray )
	{
		//return;
		float distance = 0;
		if ( plane.Raycast( ray, out distance ) )
		{
			Vector3 position = ray.origin + ray.direction  * distance;
			for ( int i = 0 ; i < Vertical ; ++i )
			{
				for ( int j = 0 ; j < Horizontal ; ++ j )
				{
					if ( screenNodes[ i, j].rectZone.Contains( position ) )
					{
						if ( screenNodes[ i, j].grid != null )
						{
							GridScript gs = screenNodes[ i, j].grid.GetComponent<GridScript>();
							gs.SetFocus( true );
						}
						if ( focusGrid != null && focusGrid != screenNodes[ i, j].grid )
						{
							GridScript gs = focusGrid.GetComponent<GridScript>();
							gs.SetFocus( false );
							
						}
						focusGrid = screenNodes[ i, j].grid;
						
					}
				}
			}
		}
	}
	
	public int TestFire( Ray ray )
	{
		float distance = 0;
		if ( plane.Raycast( ray, out distance ) )
		{
			Vector3 position = ray.origin + ray.direction  * distance;
			for ( int i = 0 ; i < Vertical ; ++i )
			{
				for ( int j = 0 ; j < Horizontal ; ++ j )
				{
					if ( screenNodes[ i, j].rectZone.Contains( position ) )
					{
						if ( screenNodes[ i, j].sphereObject == null )
						{
							return DoFire( i, j );
						}
						return 0;
					}
				}
			}
		}
		return -1;
	}
	
	public int DoFire( int vertical, int horizontal )
	{
		//left
		int x = horizontal - 1;
		while( x >= 0 )
		{
			if ( AddList( vertical, x ) )
				break;
			--x;
		}
		
		//right
		x = horizontal + 1;
		while( x < Horizontal )
		{
			if ( AddList( vertical, x ) )
				break;
			++x;
		}
		
		//top
		int y = vertical - 1;
		while( y >= 0 )
		{
			if ( AddList( y, horizontal ) )
				break;
			--y;
		}
		
		//botton
		y = vertical + 1;
		while( y < Vertical )
		{
			if ( AddList( y, horizontal ) )
				break;
			++y;
		}
		
		int result = 0;
		
		for ( int i = 0 ; i < firelist.Length ; ++i )
		{
			if ( firelist[i].Count > 1 )
			{
				result += firelist[i].Count;
				curSphereNum -= firelist[i].Count;
				foreach( GameObject j in firelist[i] )
				{
					SphereScript script = j.GetComponent<SphereScript>();
					script.parent.sphereObject = null;
					script.parent = null;
					script.SwithState( SphereScript.SphereState.State_FallDown, null );
					//GameObject.DestroyImmediate( j );
				}
			}
			firelist[i].Clear();
		}
		//SetScoreTex(score);
		
		return result;
	}
	
	public int MoveToTop( float percentMin, float percentMax )
	{
		int destroy = 0;
		for( int y = 0 ; y < Vertical ; ++y )
		{
			for( int x = 0 ; x < Horizontal ; ++x )
			{
				if ( screenNodes[ y, x].sphereObject )
				{
					if ( y == 0 )
					{
						++destroy;
						SphereScript sp =  screenNodes[ y, x].sphereObject.GetComponent<SphereScript>();
						sp.parent = null;
						SphereScript.SphereEvent se = new SphereScript.SphereEvent();
						se.moveTo = screenNodes[ y, x].centre + Vector3.up * GRID_HIGH;
						sp.SwithState( SphereScript.SphereState.State_Move, se);
						screenNodes[ y, x].sphereObject = null;
					}
					else
					{
						SphereScript sp =  screenNodes[ y, x].sphereObject.GetComponent<SphereScript>();
						sp.parent = screenNodes[ y-1, x];
						SphereScript.SphereEvent se = new SphereScript.SphereEvent();
						se.moveTo = screenNodes[ y-1, x].centre;
						sp.SwithState( SphereScript.SphereState.State_Move, se);
						screenNodes[ y-1, x].sphereObject = screenNodes[ y, x].sphereObject;
						screenNodes[ y, x].sphereObject = null;
					}
				}
			}
		}
		curSphereNum -= destroy;
		
		System.Random rnd = new System.Random();
		Object sphere = Resources.Load( "Prefab/Sphere" ) as Object;
		List<ScreenNode> nodeList = new List<ScreenNode>();
		
		
		for ( int j = 0 ; j < Horizontal ; ++j )
		{
			nodeList.Add( screenNodes[Vertical-1,j]);
		}
		
		float percent = percentMin + ( percentMax - percentMin ) * UnityEngine.Random.value;
		int newNum = (int)(Horizontal * percent);
		
		curSphereNum += newNum;
		for ( int i = 0 ; i < newNum ; ++i )
		{
			int index = rnd.Next( 0 , gameMsg.sphereTypeConfig.Length );
			int listIndex = rnd.Next( 0 , nodeList.Count );
			int flag = 0;
			nodeList.RemoveAll( delegate( ScreenNode curZone )
				{
					if ( flag == listIndex )
					{
						
						curZone.sphereObject = GameObject.Instantiate( sphere ) as GameObject;
						SphereScript script = curZone.sphereObject.GetComponent<SphereScript>();
						script.Init();
						script.SetSphereType( gameMsg.sphereTypeConfig[index].sphereType , gameMsg.sphereTypeConfig[index].color );
						curZone.sphereObject.transform.position = curZone.centre - Vector3.up * GRID_HIGH;
						SphereScript.SphereEvent se = new SphereScript.SphereEvent();
						se.moveTo = curZone.centre;
						script.SwithState( SphereScript.SphereState.State_Move, se as System.EventArgs );
						script.parent = curZone;
						++flag;
						return true;
					}
					++flag;
					return false;
				}
			);
			
		}
		
		return destroy;
	}
	
	public bool AddList(  int vertical, int horizontal )
	{
		if ( screenNodes[ vertical, horizontal ].sphereObject != null )
		{
			SphereScript script = screenNodes[ vertical, horizontal ].sphereObject.GetComponent<SphereScript>();
			if ( script != null )
			{
				firelist[ (int)script.sphereType ].Add( screenNodes[ vertical, horizontal ].sphereObject );
				return true;
			}
		}
		return false;
	}
	
	
	public void DeleteDate()
	{
		for ( int i = 0 ; i < Vertical ; ++i )
		{
			for ( int j = 0 ; j < Horizontal ; ++j )
			{
				if ( screenNodes[ i, j].sphereObject != null )
					GameObject.DestroyImmediate( screenNodes[ i, j].sphereObject );
			}
		}
	}
	
	public void ReleaseScreen()
	{
		for ( int i = 0 ; i < Vertical ; ++i )
		{
			for ( int j = 0 ; j < Horizontal ; ++j )
			{
				if ( screenNodes[ i, j].grid != null )
					GameObject.DestroyImmediate( screenNodes[ i, j].grid );
			}
		}
	}

	
	public GameMsgScript	gameMsg;
	
	public ScreenNode[,]	screenNodes;
	public int				Vertical = 10;
	public int				Horizontal = 10;
	public int				curSphereNum = 0;
	public GameObject		focusGrid;
	
	List<GameObject>[] firelist = new List<GameObject>[(int)GameMsgScript.SphereType.Type_Num];
	
	public Plane plane = new Plane( -Vector3.forward, 0 );
}
